using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
using CommunityToolkit.HighPerformance;
using Microsoft.Xna.Framework;
using TinyPinyin;

namespace RSCore;

/// <summary>
/// 杂项
/// </summary>
public static class RSExtensions
{
	public static string GetDefaultDisplayName(this string name)
	{
		return Regex.Replace(name, "([A-Z])", " $1");
	}

	public static Vector2 Approach(this Vector2 start, Vector2 end, float distance)
	{
		if ((start - end).LengthSquared() < distance * distance)
		{
			return end;
		}
		else
		{
			return start + Vector2.Normalize(end - start) * distance;
		}
	}

	public static void WriteProperty(this StreamWriter writer, string property, string? annotation = null, [CallerArgumentExpression(nameof(property))] string name = null!)
	{
		writer.WriteLine($"@@ {name} @@");
		if (annotation != null)
		{
			foreach (var line in annotation.Tokenize('\n'))
			{
				writer.Write('-');
				writer.WriteLine(line);
			}
		}
		foreach (var line in property.Tokenize('\n'))
		{
			writer.Write('+');
			writer.WriteLine(line);
		}
		writer.WriteLine();
	}

	public static Dictionary<string, string> ReadProperties(this StreamReader reader)
	{
		string? name = null;
		var properties = new Dictionary<string, string>();
		string? line;
		while ((line = reader.ReadLine()) != null)
		{
			if (line.StartsWith("@@", StringComparison.Ordinal) && line.EndsWith("@@", StringComparison.Ordinal))
			{
				name = line[2..^2].Trim().ToString();
				properties[name] = string.Empty;
				continue;
			}

			if (name == null || line.Length == 0)
			{
				continue;
			}

			if (line[0] == '+')
			{
				properties[name] += line[1..].ToString();
			}
		}
		return properties;
	}

	public static string GetText(this Dictionary<string, string> dict, string key)
	{
		return dict.TryGetValue(key, out var val) ? val : string.Empty;
	}

	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static bool SmartMatch(this string str, ReadOnlySpan<char> pattern) => SmartMatch([.. str], pattern);

	public static bool SmartMatch(this ReadOnlySpan<char> str, ReadOnlySpan<char> pattern)
	{
		if (pattern.Length == 0)
		{
			return true;
		}
		int wordStart = 0;
		int matchProcess = 0;
		static bool MatchWord(ReadOnlySpan<char> word, ReadOnlySpan<char> pattern, ref int matchProcess)
		{
			for (int j = 0; j < word.Length; j++)
			{
				if (char.ToUpper(word[j]) != char.ToUpper(pattern[matchProcess]))
				{
					return false;
				}
				if (++matchProcess == pattern.Length)
				{
					return true;
				}
			}
			return false;
		}
		for (int i = 0; i < str.Length; i++)
		{
			if (PinyinHelper.IsChinese(str[i]))
			{
				var pinyin = PinyinHelper.GetPinyin(str[i]);
				for (int j = 0; j < pinyin.Length; j++)
				{
					if (pinyin[j] != char.ToUpper(pattern[matchProcess]))
					{
						break;
					}
					if (++matchProcess == pattern.Length)
					{
						return true;
					}
				}
			}
			else if (char.IsUpper(str[i]) && wordStart != i)
			{
				if (MatchWord(str[wordStart..i], pattern, ref matchProcess))
				{
					return true;
				}
				wordStart = i;
			}
			else if (!char.IsLower(str[i]))
			{
				if (i != wordStart && MatchWord(str[wordStart..i], pattern, ref matchProcess))
				{
					return true;
				}
				if (str[i] == pattern[matchProcess])
				{
					if (++matchProcess == pattern.Length)
					{
						return true;
					}
				}
			}
		}

		if (MatchWord(str[wordStart..], pattern, ref matchProcess))
		{
			return true;
		}

		return false;
	}
}